package com.xiaoma.aes.encryption.symmetrical;

import com.xiaoma.aes.util.BaseUtil;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;


/**
 * 对称加密算法
 * @author Knight-Ran 2017年3月11日 下午4:42:36
 */
public final class SymetricalEncrytion{
    
    
    /**
     * DES加密算法
     */
    public static final String ALGORITHM_DES = "DES";
    
    /**
     * DESede加密算法
     */
    public static final String ALGORITHM_DESEDE = "DESede";
    
    /**
     * AES加密算法
     */
    public static final String ALGORITHM_AES = "AES";
    
    /**
     * Blowfish加密算法
     */
    public static final String ALGORITHM_BLOWFISH = "Blowfish";
    
    /**
     * RC2加密算法
     */
    public static final String ALGORITHM_RC2 = "RC2";
    
    /**
     * RC4加密算法
     */
    public static final String ALGORITHM_RC4 = "RC4";
    

    /**
     * 无参构造
     */
    private SymetricalEncrytion(){}
    
    /**
     * Key 值转换
     * @param algorithm
     * @param key
     * @return
     * @author Knight-Ran
     * @date 2017年3月12日 下午2:47:26
     */
    public static Key toKey(String algorithm, byte [] key){
        if(ALGORITHM_DES.equals(algorithm)){
            try{
                DESKeySpec dks = new DESKeySpec(key);
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
                SecretKey secretKey = keyFactory.generateSecret(dks);
                return secretKey;
            }catch(InvalidKeyException e){
//                LOGGER.error("无效的KEY : invalid encoding, wrong length, uninitialized, etc", e);
//                throw new EncryptionException("无效的KEY : invalid encoding, wrong length, uninitialized, etc", e);
            }catch(NoSuchAlgorithmException e){
//                LOGGER.error("无此加密算法", e);
//                throw new EncryptionException("无此加密算法", e);
            }catch(InvalidKeySpecException e){
//                LOGGER.error("无效的KEY : invalid key specifications.", e);
//                throw new EncryptionException("无效的KEY : invalid key specifications.", e);
            }
            
        }
        
        return new SecretKeySpec(key, algorithm);
    }
    
    /**
     * 解密
     * @param algorithm
     * @param data
     * @param key
     * @return
     * @author Knight-Ran
     * @date 2017年3月12日 下午3:02:51
     */
    public static byte [] decrypt(String algorithm, byte [] data, byte [] key){
        Key k = toKey(algorithm, key);
        
        Cipher cipher;
        try{
            cipher = Cipher.getInstance(algorithm.toString());
            cipher.init(2, k);
            
            return cipher.doFinal(data);
        }catch(NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
                | BadPaddingException e){
//            LOGGER.error("解密失败", e);
//            throw new EncryptionException("解密失败", e);
        }

        return null;
        
    }
    
    
    /**
     * DES 解密算法
     * @param encrypitonData
     * @param key
     * @return
     * @author Knight-Ran
     * @date 2017年3月12日 下午3:02:59
     */
    public static String decryptByDES(String encrypitonData, String key){
        try{
            return new String(
                    decrypt(ALGORITHM_DES, BaseUtil.parseHexStr2Byte(encrypitonData),
                            initKey(ALGORITHM_DES, key.getBytes("UTF_8"))),
                    "UTF_8");
        }catch(NoSuchAlgorithmException | UnsupportedEncodingException e){
//            LOGGER.error("解密失败", e);
//            throw new EncryptionException("解密失败", e);
        }

        return null;
        
    }
    
    
    /**
     * 加密
     * @param algorithm
     * @param data
     * @param key
     * @return
     * @author Knight-Ran
     * @date 2017年3月12日 下午3:02:43
     */
    public static byte [] encrypt(String algorithm, byte [] data, byte [] key){
        Key k = toKey(algorithm, key);
        Cipher cipher;
        try{
            cipher = Cipher.getInstance(algorithm.toString());
            cipher.init(1, k);
            
            return cipher.doFinal(data);
        }catch(NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
                | BadPaddingException e){
//            LOGGER.error("加密失败", e);
//            throw new EncryptionException("加密失败", e);
        }

        return null;
        
    }
    
    /**
     * DES 加密算法
     * @param key
     * @return
     * @author Knight-Ran
     * @date 2017年3月12日 下午3:02:59
     */
    public static String encryptByDES(String data, String key){
        try{
            return BaseUtil.parseByte2HexStr(encrypt(ALGORITHM_DES, data.getBytes("UTF_8"),
                    initKey(ALGORITHM_DES, key.getBytes("UTF-8"))));
        }catch(UnsupportedEncodingException | NoSuchAlgorithmException e){
//            LOGGER.error("加密失败", e);
//            throw new EncryptionException("加密失败", e);
        }

        return null;
        
    }
    
    
    /**
     * 初始化密钥
     * 
     * @param algorithm
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static byte [] initKey(String algorithm) throws NoSuchAlgorithmException{
        return initKey(algorithm, null);
    }
    
    /**
     * 初始化密钥
     * 
     * @param algorithm
     * @param seed
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static byte [] initKey(String algorithm, byte [] seed) throws NoSuchAlgorithmException{
        SecureRandom secureRandom = null;
        
        secureRandom = SecureRandom.getInstance("SHA1PRNG");
        if(seed != null){
            secureRandom.setSeed(seed);
        }
        
        KeyGenerator kg = KeyGenerator.getInstance(algorithm);
        kg.init(secureRandom);
        
        return kg.generateKey().getEncoded();
    }
    
    
    /*    public static void main(String [] args){
        String data = "192000088333131";
        String key = "79CF95A17816002D2ABC10DFFA3F18BCCE0EFEA5285FE86784ADB68FCA5BE1A4";
        
        
        String encrypitonData = "645601703AA2E425A66ABE4E49E18DAD";
    //        String dec = encryptByDES(encrypitonData, key);
        String dec = decryptByDES(encrypitonData, key);
        
        System.out.println(dec);
    }*/
    
}
